import { _decorator, Component, Node,systemEvent,SystemEvent,EventTouch,Vec3,v3,UITransform,View,Size,Graphics ,Vec2, v2,Color,color,Sprite,Tween,tween,instantiate} from 'cc';
import {Ball} from "../Ball";
import {BallColorIdx, NativeEvt} from "../GameConfig";
import {GameMain} from "../GameMain";
import Line from "./Line";
import {AudioClipID, AudioManager} from "../AudioManager";

import SegmentDetect from "./SegmentDetect";
import LevelCfgItem from "../LevelCfgItem";
import Platform from "../Platform";


const { ccclass, property } = _decorator;

@ccclass('LineGame')
export class LineGame extends Component {

    public gameBoardNode:Node=null;
    public gameBoradUITrans:UITransform=null;
    public ballsParentNode:Node=null;

    public touchTransInput:Vec3=v3(0,0,0);
    public touchTransOutput:Vec3=v3(0,0,0);

    public graphics:Graphics=null;

    public lineCircleSprite0:Sprite=null;
    public lineCircleSprite1:Sprite=null;
    public errorCrossNode:Node=null;

    public lastTouchPos:Vec2=v2(99999,99999);
    public movDelta:Vec2=v2(0,0);
    public isPressed:boolean=false;

    public balls:Array<Ball>=[];

    public curLine:Line=null;
    public lines:Array<Line>=[];

    public intersectionPoint=[0,0];

    public inited:boolean=false;

    onLoad()
    {
        this.init();

    }

    public init()
    {
        if(this.inited)
            return;

        this.gameBoardNode=this.node.getChildByName("gameBoard");
        this.gameBoradUITrans=this.gameBoardNode.getComponent(UITransform);
        this.ballsParentNode=this.gameBoardNode.getChildByName("ballsParent");

        /*
        let ballComponent:Ball=null;
        for(let i=0;i<this.ballsParentNode.children.length;i++)
        {
            ballComponent=this.ballsParentNode.children[i].getComponent("Ball");
            this.balls.push(ballComponent);
            if(i===0 || i===1)
                ballComponent.setVal(BallColorIdx.p);
            else if(i===2 || i===3)
                ballComponent.setVal(BallColorIdx.g);
        }*/

        this.graphics=this.gameBoardNode.getChildByName("graphics").getComponent(Graphics);
        this.graphics.strokeColor.set(color(0, 0, 255, 255));

        this.lineCircleSprite0=this.gameBoardNode.getChildByName("lineCircle").getChildByName("sprite").getComponent(Sprite);
        this.lineCircleSprite1=this.gameBoardNode.getChildByName("lineCircle").getChildByName("sprite1").getComponent(Sprite);
        this.errorCrossNode=this.gameBoardNode.getChildByName("errorCross");

        this.inited=true;
    }

    public clearBalls()
    {
        this.balls.splice(0, this.balls.length);
        this.ballsParentNode.destroyAllChildren();
        this.ballsParentNode.removeAllChildren(true);
    }

    public resetCurLevel()
    {
        this.isPressed=false;
        this.resetLastTouchPos();
        this.curLine=null;
        this.lineCircleSprite0.node.parent.active=false;
        this.lines.splice(0, this.lines.length);

        for(let i=0;i<this.balls.length;i++)
        {
            this.balls[i].setLineConnected(false);
        }
    }

    public createBalls()
    {
        this.clearBalls();
        let levelCfg:LevelCfgItem=GameMain.getCurLevelCfg();

        for(let i=0;i<levelCfg.lineGameBalls.length;i++)
        {
            let val:number=levelCfg.lineGameBalls[i].val;

            let ball0=instantiate(GameMain.instance.ballPrefab);
            this.ballsParentNode.addChild(ball0);
            let ball0Component:Ball=ball0.getComponent("Ball");
            ball0Component.setVal(val);
            ball0.setPosition(levelCfg.lineGameBalls[i].pos0.x, levelCfg.lineGameBalls[i].pos0.y, 0);
            ball0.setScale(0.85, 0.85, 1);
            this.balls.push(ball0Component);

            let ball1=instantiate(GameMain.instance.ballPrefab);
            this.ballsParentNode.addChild(ball1);
            let ball1Component:Ball=ball1.getComponent("Ball");
            ball1Component.setVal(val);
            ball1.setPosition(levelCfg.lineGameBalls[i].pos1.x, levelCfg.lineGameBalls[i].pos1.y, 0);
            ball1.setScale(0.85, 0.85, 1);
            this.balls.push(ball1Component);
        }

    }

    start() {
        this.addEvent();
    }

    addEvent()
    {
        //systemEvent.on(SystemEvent.EventType.TOUCH_START, this.onTouchStart, this);

        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_START, this.onTouchStart, this);
        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_END, this.onTouchEnd, this);
        this.gameBoardNode.on(SystemEvent.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
    }

    public updateTouchTransOutput(touchX:number, touchY:number)
    {
        this.touchTransInput.x=touchX;
        this.touchTransInput.y=touchY;
        this.touchTransInput.z=0;
        this.gameBoradUITrans.convertToNodeSpaceAR(this.touchTransInput, this.touchTransOutput);
    }

    onTouchStart(event:EventTouch)
    {
        this.isPressed=true;
        let touchX=event.getLocationX() * GameMain.instance.designXRatio;
        let touchY=event.getLocationY() * GameMain.instance.designYRatio;

        //转换到ballParent坐标系下
        this.updateTouchTransOutput(touchX, touchY);
        this.lastTouchPos.x=this.touchTransOutput.x;
        this.lastTouchPos.y=this.touchTransOutput.y;

        let touchBall:Ball=null;
        for(let i=0;i<this.balls.length;i++)
        {
            if(this.balls[i].isInRect(v2(this.touchTransOutput.x, this.touchTransOutput.y)))
            {
                touchBall=this.balls[i];
                break;
            }
        }

        if(touchBall!==null)
        {
            touchBall.onPressedInLineGame();
            if(!touchBall.lineConnected)
            {
                touchBall.setLineConnected(true);

                //this.graphics.moveTo(this.touchTransOutput.x, this.touchTransOutput.y);
                //this.graphics.strokeColor=touchBall.getStripColor();

                this.curLine = new Line();
                this.curLine.setBeginBall(touchBall);
                this.curLine.addPoints(this.touchTransOutput.x, this.touchTransOutput.y);
            }
            else
            {
                //取消连线
                this.removeLine(touchBall);

                //通知mainUI
                GameMain.instance.mainUI.notifyBallConnectedInLineGame(touchBall.val , false);
            }
        }
    }

    public removeLine(ball:Ball)
    {
        if(!ball)
            return;
        for(let i=0;i<this.lines.length;i++)
        {
            if(this.lines[i].beginBall===ball || this.lines[i].endBall===ball)
            {
                this.lines[i].beginBall.setLineConnected(false);
                this.lines[i].endBall.setLineConnected(false);
                this.lines.splice(i, 1);
                return;
            }
        }
    }

    public activeLineCircle()
    {
        this.lineCircleSprite0.node.parent.active=true;
        this.lineCircleSprite0.node.parent.setScale(1, 1 ,1);
        let ballColor:Color=this.curLine.beginBall.getStripColor();
        this.lineCircleSprite0.color=color(ballColor.r, ballColor.g, ballColor.b, 100);
        this.lineCircleSprite1.color=color(ballColor.r, ballColor.g, ballColor.b, 45);
    }

    onTouchMove(event:EventTouch)
    {
        //beginBall不能为空
        if(this.curLine===null)
            return;

        let touchX=event.getLocationX() * GameMain.instance.designXRatio;
        let touchY=event.getLocationY() * GameMain.instance.designYRatio;
        this.updateTouchTransOutput(touchX, touchY);
        if(this.touchTransOutput.y>330)
            this.touchTransOutput.y=330;
        if(this.touchTransOutput.y<-330)
            this.touchTransOutput.y=-330;
        if(this.touchTransOutput.x>330)
            this.touchTransOutput.x=330;
        if(this.touchTransOutput.x<-330)
            this.touchTransOutput.x=-330;

        if(this.isLastTouchPosValid())
        {
            this.movDelta.x=this.touchTransOutput.x;
            this.movDelta.y=this.touchTransOutput.y;
            this.movDelta.subtract(this.lastTouchPos);
            if(this.movDelta.lengthSqr()>=49)
            {

                //转换到ballParent坐标系下
                //this.graphics.lineTo(this.touchTransOutput.x, this.touchTransOutput.y);
                //this.graphics.stroke();

                //curLine 和 已经存在的line 的相交测试
                let intersection:boolean=this.lineIntersectionDetect();
                if(intersection)
                {
                    this.curLine.beginBall.setLineConnected(false);
                    this.curLine=null;
                    this.lineCircleSprite0.node.parent.active=false;
                    this.showErrorCross(this.touchTransOutput.x, this.touchTransOutput.y);

                    //通知mainUI
                    GameMain.instance.mainUI.notifyBallConnectedInLineGame(0 , false, false);
                    return;
                }

                let touchBall:Ball=null;
                for(let i=0;i<this.balls.length;i++)
                {
                    if(this.balls[i].isInRect(v2(this.touchTransOutput.x, this.touchTransOutput.y)))
                    {
                        touchBall=this.balls[i];
                        break;
                    }
                }

                //连接到值不同的球,显示'x'提示，同时清除当前画线
                if(touchBall!==null && this.curLine.beginBall.val!==touchBall.val)
                {
                    this.curLine.beginBall.setLineConnected(false);
                    this.curLine=null;
                    this.lineCircleSprite0.node.parent.active=false;
                    this.showErrorCross(this.touchTransOutput.x, this.touchTransOutput.y);

                    //通知mainUI
                    GameMain.instance.mainUI.notifyBallConnectedInLineGame(touchBall.val , false, false);

                    return;
                }

                //连接到颜色相同的球
                if(touchBall!==null && touchBall.lineConnected===false && this.curLine.beginBall.val===touchBall.val)
                {
                    AudioManager.playClip(AudioClipID.Tip);
                    touchBall.onPressedInLineGame();
                    touchBall.setLineConnected(true);
                    this.lineCircleSprite0.node.parent.active=false;

                    this.curLine.setEndBall(touchBall);
                    this.curLine.addPoints(this.touchTransOutput.x, this.touchTransOutput.y);
                    this.lines.push(this.curLine);

                    this.curLine=null;

                    //通知mainUI
                    GameMain.instance.mainUI.notifyBallConnectedInLineGame(touchBall.val , true);

                    return;
                }

                if(this.lineCircleSprite0.node.parent.active===false)
                    this.activeLineCircle();

                this.lastTouchPos.x=this.touchTransOutput.x;
                this.lastTouchPos.y=this.touchTransOutput.y;

                this.curLine.addPoints(this.touchTransOutput.x, this.touchTransOutput.y);

                this.lineCircleSprite1.node.parent.setPosition(this.touchTransOutput.x, this.touchTransOutput.y, 0);
            }
        }
        else
        {
            this.lastTouchPos.x=this.touchTransOutput.x;
            this.lastTouchPos.y=this.touchTransOutput.y;
        }
    }

    public lineIntersectionDetect():boolean
    {
        if(this.curLine===null)
            return false;

        for(let i=0;i<=this.curLine.points.length-2;i++)
        {
            for(let j=0;j<this.lines.length;j++)
            {
                for(let k=0;k<this.lines[j].points.length-2;k++)
                {
                    let intersection:boolean=SegmentDetect.segDetect(this.intersectionPoint,[this.curLine.points[i].x,this.curLine.points[i].y],[this.curLine.points[i+1].x,this.curLine.points[i+1].y],
                        [this.lines[j].points[k].x,this.lines[j].points[k].y], [this.lines[j].points[k+1].x,this.lines[j].points[k+1].y]);
                    if(intersection)
                    {
                        //console.log("** 线段相交  intersection="+JSON.stringify(this.intersectionPoint));
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public showErrorCross(x:number, y:number)
    {
        AudioManager.playClip(AudioClipID.Error);
        this.errorCrossNode.active=true;
        this.errorCrossNode.setPosition(x, y, 0);
        this.scheduleOnce(()=>{
            this.errorCrossNode.active=false;
        }, 0.8);
    }

    //Touch结束的逻辑
    onTouchEnd(event:EventTouch)
    {
        let touchX=event.getLocationX();
        let touchY=event.getLocationY();

        this.touchEnd();
    }

    onTouchCancel(event:EventTouch)
    {
        this.touchEnd();
    }

    public touchEnd()
    {
        this.isPressed=false;
        this.resetLastTouchPos();
        this.lineCircleSprite0.node.parent.active=false;

        if(this.curLine!==null && this.curLine.beginBall!==null)
            this.curLine.beginBall.setLineConnected(false);
        this.curLine=null;
    }

    public resetLastTouchPos()
    {
        this.lastTouchPos.x=99999;
        this.lastTouchPos.y=99999;
    }

    public isLastTouchPosValid():boolean
    {
        if(this.lastTouchPos.x>=99990 || this.lastTouchPos.y>=99990)
            return false;
        return true;
    }

    public skipClicked()
    {
        GameMain.instance.setVedioAwardScene(NativeEvt.VedioSkipLineGame);
        Platform.playVideoAd(() =>
        {
            this.videoAward();
        });
    }

    public helpClicked()
    {
        GameMain.instance.lineGameHelpUI.show();
    }

    public videoAward()
    {
        if(!GameMain.instance.curLevelPassed)
        {
            GameMain.instance.curLevelPassed=true;
            GameMain.instance.nextLevel();
        }
        GameMain.instance.backToStartUI();
    }

    update(deltaTime: number)
    {
        if(this.graphics!==null)
        {
            this.graphics.clear();
            if (this.curLine !== null)
            {
                this.curLine.draw(this.graphics);
            }

            for(let i=0;i<this.lines.length;i++)
            {
                this.lines[i].draw(this.graphics);
            }
        }
    }
}

